/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ScannerParser;

import java.util.*;
import goldengine.*;
/**
 *
 * @author jefoutta
 */
public class SyntaxTree{
    private SyntaxTree parent;
    private LinkedList<SyntaxTree> children;
    private String element;
    public static LinkedList<SyntaxTree> brothers = new LinkedList();
    private static LinkedList<GDA> gdaParameters;
    private static boolean gdaParametersbool;
    private Reduction reduction;
    private boolean hasReduction;
    private String type;
    private GDA gda;
    private Label labelTrue;
    private Label labelFalse;
    private Label labelNext;
    private String dataCode;
    private ThreeDirectionInstruction code;
    private String next;
    private String data;
    private int width;
    public static ThreeDirectionInstruction middleCode = new ThreeDirectionInstruction();
    public static LinkedList<String> middleDataCode = new LinkedList();

    //Temporal Variables that will be use in the symbolTable generation and type verification
    private String[] stringTemporal = new String[4];
    private String[] stringTemporal2 = new String[4];
    private Symbol[] symbolTemporal = new Symbol[2];
    private Integer integerTemporal;
    private SymbolTable symbolTableTemporal;
    private boolean[] booleanTemporal = new boolean[2];


    public SyntaxTree(SyntaxTree ttree){
        this.element = ttree.element;
        this.children = ttree.children;
    }

    public SyntaxTree(String ttext){
        String[] split = null;
        this.hasReduction = false;
        if (ttext.contains("::=")){
            split = ttext.split(" ::= ");
            element = split[0];
            if(split.length > 1){
                split = split[1].split(" ");
            }else{
                split = "epsilon ".split(" ");
            }
        }else{
            element = ttext;
        }
        children = new LinkedList();
        if (split != null){
            for(int i = 0; i < split.length; i++){
                children.add(new SyntaxTree(split[i]));
                this.setAsParentTo(this.children.getLast());
            }
        }
    }

    public SyntaxTree(String ttext, LinkedList<SyntaxTree> tchildren){
        element = ttext;
        children = tchildren;
    }

    public SyntaxTree(Reduction treduction){
        this.children = new LinkedList();
        this.reduction = treduction;
        this.hasReduction = true;
        this.element = treduction.getParentRule().getRuleNonTerminal().getName();
        if(treduction.getTokenCount() == 0){
            this.children.add(new SyntaxTree("epsilon"));
            this.setAsParentTo(this.children.getLast());
        }else{
            for(int i = 0; i < treduction.getTokenCount(); i++){
                if(treduction.getToken(i).getPSymbol().getKind() == 1){
                    this.children.add(new SyntaxTree(treduction.getToken(i).getName()));
                    this.setAsParentTo(this.children.getLast());
                }else{
                    this.children.add(new SyntaxTree((Reduction)treduction.getToken(i).getData()));
                    this.setAsParentTo(this.children.getLast());
                }
            }
        }
    }

    /*public void addInverter(SyntaxTree tparent){
        SyntaxTree ttree = this;
        brothers.add(new SyntaxTree(this.text, this.children));
        boolean atLeastOne = false;
        LinkedList<SyntaxTree> tchildren = tparent.getChildren();
        for(int i = 0; i < tchildren.size(); i++){
            for(int j = 0; j < brothers.size(); j++){
                if((tchildren.get(i).gettext().equals(brothers.get(j).gettext()))&&(tchildren.get(i).gettext().matches("<(.)*>"))){
                    tparent.setChild(i, brothers.remove(j));
                    atLeastOne = true;
                }
            }
        }
        if(atLeastOne){
            this.text = tparent.text;
            this.children = tparent.children;
        }else
            brothers.add(tparent);
    }*/

    public void setAsParentTo(SyntaxTree tchild){
        tchild.parent = this;
    }

    public void add(SyntaxTree ttree){
        
    }

    public String getAtributesAndSymbols(SyntaxTree tree){
        
        String atribute = null;
        switch(tree.reduction.getParentRule().getTableIndex())
        {
            /*case 0:
            //<Program> ::= class Program '{' <kleene_declaration> '}'
            break;
            case 1:
            //<kleene_declaration> ::= <declaration> <kleene_declaration>
            break;
            case 2:
            //<kleene_declaration> ::=
            break;
            case 3:
            //<declaration> ::= <structDeclaration>
            break;
            case 4:
            //<declaration> ::= <varDeclaration>
            break;
            case 5:
            //<declaration> ::= <methodDeclaration>
            break;*/
            case 6:{
            //<varDeclaration> ::= <Type> id <varDecl 1> ';'
                stringTemporal[0] = (String)tree.getReduction().getToken(1).getData();
                if(!SymbolTable.actualSymbolTable.isAlreadyDefined("variable " + stringTemporal[0])){
                    stringTemporal[1] = tree.getAtributesAndSymbols(tree.getChildren().get(2));
                    if(!stringTemporal[1].equals("one")){
                        integerTemporal = Integer.parseInt(stringTemporal[1]);
                        if(integerTemporal > 1)
                            SymbolTable.actualSymbolTable.addSymbol(new Variable(stringTemporal[0],tree.getAtributesAndSymbols(tree.getChildren().get(0)),tree.getAtributesAndSymbols(tree.getChildren().get(2))));
                        else
                            Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": invalid array size");
                        atribute = "void";
                    }else{
                        stringTemporal[1] = "1";
                        SymbolTable.actualSymbolTable.addSymbol(new Variable(stringTemporal[0],tree.getAtributesAndSymbols(tree.getChildren().get(0)),stringTemporal[1]));
                    }
                }else{
                    atribute = "error";
                    Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": variable already defined");
                }
            }
            break;
            case 7:{
            //<varDecl 1> ::= '[' num ']'
                atribute = (String) tree.reduction.getToken(1).getData();
            }
            break;
            case 8:{
            //<varDecl 1>
                atribute = "one";
            }
            break;
            case 9:{
            //<structDeclaration> ::= struct id '{' <kleene_varDeclaration> '}'
                stringTemporal[0] = (String)tree.getReduction().getToken(1).getData();
                if(!SymbolTable.actualSymbolTable.isAlreadyDefined("struct " + stringTemporal[0])){
                    SymbolTable.actualSymbolTable.addSymbol(new Struct((String)tree.getReduction().getToken(1).getData()));
                    tree.getAtributesAndSymbols(tree.getChildren().get(3));
                    SymbolTable.actualSymbolTable.returnToParent();
                    atribute = (String) tree.getReduction().getToken(1).getData();
                }else{
                    atribute = "error";
                    Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": struct already defined");
                }
            }
            break;
            /*case 10:
            //<kleene_varDeclaration> ::= <varDeclaration> <kleene_varDeclaration>
            break;
            case 11:
            //<kleene_varDeclaration> ::=
            break;*/
            case 12:{
            //<methodDeclaration> ::= <Type> id '(' <opt_parameter> ')' <block>
                SymbolTable.actualSymbolTable.addSymbol(new Method((String)tree.getReduction().getToken(1).getData(),tree.getAtributesAndSymbols(tree.getChildren().get(0))));
                if(SymbolTable.actualSymbolTable.getParent().isMoreThanOnes("method "+ tree.getAtributesAndSymbols(tree.getChildren().get(3)))){
                        atribute = "error";
                        Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": method already defined");
                }else{
                    atribute = "void";
                }
                tree.getAtributesAndSymbols(tree.getChildren().get(5));
                SymbolTable.actualSymbolTable.returnToParent();
            }
            break;
            /*case 13:
            //<opt_parameter> ::= <parameter list>
            break;
            case 14:
            //<opt_parameter> ::=
            break;
            case 15:
            //<parameter list> ::= <parameter>
            break;
            case 16:
            //<parameter list> ::= <parameter list> ',' <parameter>
            break;*/
            case 17:{
            //<Type> ::= int
                atribute = tree.reduction.getToken(0).getPSymbol().getText();
            }
            break;
            case 18:{
            //<Type> ::= char
                atribute = tree.reduction.getToken(0).getPSymbol().getText();
            }
            break;
            case 19:{
            //<Type> ::= boolean
                atribute = tree.reduction.getToken(0).getPSymbol().getText();
            }
            break;
            case 20:{
            //<Type> ::= void
                atribute = tree.reduction.getToken(0).getPSymbol().getText();
            }
            break;
            case 21:{
            //<Type> ::= struct id
                atribute = (String)tree.reduction.getToken(1).getData();
            }
            break;
            case 22:{
            //<Type> ::= <structDeclaration>
                atribute = tree.getAtributesAndSymbols(tree.getChildren().get(0));
            }
            break;
            case 23:{
            //<parameter> ::= <Type> id
                stringTemporal[0] = (String)tree.getReduction().getToken(1).getData();
                stringTemporal[1] = tree.getAtributesAndSymbols(tree.getChildren().get(0));
                if(!SymbolTable.actualSymbolTable.isAlreadyDefined("variable " + stringTemporal[0])){
                    SymbolTable.actualSymbolTable.getParent().getLastSymbol().addParameter(stringTemporal[0], stringTemporal[1], "1");
                    //SymbolTable.actualSymbolTable.addSymbol(new Variable(stringTemporal[0],stringTemporal[1],"1"));
                    SymbolTable.actualSymbolTable.addSymbol(SymbolTable.actualSymbolTable.getParent().getLastSymbol().getLastParameter());
                    atribute = SymbolTable.actualSymbolTable.getParent().getLastSymbol().getFirm();
                }else{
                    atribute = "error";
                    Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": variable already defined");
                }
            }
            break;
            case 24:{
            //<parameter> ::= <Type> id '[' ']'
                stringTemporal[0] = (String)tree.getReduction().getToken(1).getData();
                stringTemporal[1] = tree.getAtributesAndSymbols(tree.getChildren().get(0));
                if(!SymbolTable.actualSymbolTable.isAlreadyDefined("variable " + stringTemporal[0])){
                    SymbolTable.actualSymbolTable.getParent().getLastSymbol().addParameter(stringTemporal[0], stringTemporal[1],"2");
                    //SymbolTable.actualSymbolTable.addSymbol(new Variable(stringTemporal[0],stringTemporal[1],"2"));
                    SymbolTable.actualSymbolTable.addSymbol(SymbolTable.actualSymbolTable.getParent().getLastSymbol().getLastParameter());
                    atribute = SymbolTable.actualSymbolTable.getParent().getLastSymbol().getFirm();
                }else{
                    atribute = "error";
                    Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": variable already defined");
                }
            }
            break;
            /*case 25:
            //<block> ::= '{' <kleene_varDeclaration> <kleene_statement> '}'
            break;
            case 26:
            //<kleene_statement> ::= <statement> <kleene_statement>
            break;
            case 27:
            //<kleene_statement> ::=
            break;
            case 28:
            //<statement> ::= <block>
            break;
            case 29:
            //<statement> ::= <selection>
            break;
            case 30:
            //<statement> ::= <iteration>
            break;
            case 31:
            //<statement> ::= <return> ';'
            break;
            case 32:
            //<statement> ::= <assign> ';'
            break;
            case 33:
            //<statement> ::= <opt_expression> ';'
            break;
            case 34:
            //<selection> ::= if '(' <expression> ')' <block> <opt_else_block>
            break;
            case 35:
            //<opt_else_block> ::= else <block>
            break;
            case 36:
            //<opt_else_block> ::=
            break;
            case 37:
            //<iteration> ::= while '(' <expression> ')' <block>
            break;
            case 38:
            //<return> ::= return <opt_expression>
            break;
            case 39:
            //<assign> ::= <location> '=' <expression>
            break;
            case 40:
            //<opt_expression> ::= <expression>
            break;
            case 41:
            //<opt_expression> ::=
            break;
            case 42:
            //<expression> ::= <Rel Exp> <conditionalop> <expression>
            break;
            case 43:
            //<expression> ::= <Rel Exp>
            break;
            case 44:
            //<Rel Exp> ::= <Add Exp> <relop> <Rel Exp>
            break;
            case 45:
            //<Rel Exp> ::= <Add Exp>
            break;
            case 46:
            //<Add Exp> ::= <Mult Exp> <addop> <Add Exp>
            break;
            case 47:
            //<Add Exp> ::= <Mult Exp>
            break;
            case 48:
            //<Mult Exp> ::= <Negate Exp> <mulop> <Mult Exp>
            break;
            case 49:
            //<Mult Exp> ::= <Negate Exp>
            break;
            case 50:
            //<Negate Exp> ::= '-' <Value>
            break;
            case 51:
            //<Negate Exp> ::= '!' <Value>
            break;
            case 52:
            //<Negate Exp> ::= <Value>
            break;
            case 53:
            //<conditionalop> ::= '&&'
            break;
            case 54:
            //<conditionalop> ::= '||'
            break;
            case 55:
            //<relop> ::= '<='
            break;
            case 56:
            //<relop> ::= '<'
            break;
            case 57:
            //<relop> ::= '>'
            break;
            case 58:
            //<relop> ::= '>='
            break;
            case 59:
            //<relop> ::= '=='
            break;
            case 60:
            //<relop> ::= '!='
            break;
            case 61:
            //<addop> ::= '+'
            break;
            case 62:
            //<addop> ::= '-'
            break;
            case 63:
            //<mulop> ::= '*'
            break;
            case 64:
            //<mulop> ::= '/'
            break;
            case 65:
            //<mulop> ::= '%'
            break;
            case 66:
            //<Value> ::= <literal>
            break;
            case 67:
            //<Value> ::= '(' <expression> ')'
            break;
            case 68:
            //<Value> ::= <methodCall>
            break;
            case 69:
            //<Value> ::= <location>
            break;
            case 70:
            //<location> ::= <simpleLocation> '.' <location>
            break;
            case 71:
            //<location> ::= <simpleLocation>
            break;
            case 72:
            //<simpleLocation> ::= id '[' <expression> ']'
            break;
            case 73:
            //<simpleLocation> ::= id
            break;
            case 74:
            //<methodCall> ::= id '(' <opt_arg_separated> ')'
            break;
            case 75:
            //<opt_arg_separated> ::= <arg list>
            break;
            case 76:
            //<opt_arg_separated> ::=
            break;
            case 77:
            //<arg list> ::= <arg>
            break;
            case 78:
            //<arg list> ::= <arg list> ',' <arg>
            break;
            case 79:
            //<arg> ::= <expression>
            break;
            case 80:
            //<literal> ::= <int_literal>
            break;
            case 81:
            //<literal> ::= <char_literal>
            break;
            case 82:
            //<literal> ::= <bool_literal>
            break;
            case 83:
            //<int_literal> ::= num
            break;
            case 84:
            //<char_literal> ::= character
            break;
            case 85:
            //<bool_literal> ::= true
            break;
            case 86:
            //<bool_literal> ::= false
            break;*/
            default:{
                atribute = null;
                for(int i = 0; i < tree.getChildren().size(); i++)
                    if(tree.getChildren().get(i).hasReduction())
                        atribute = tree.getAtributesAndSymbols(tree.getChildren().get(i));
            }break;
        }
        return atribute;
    }

    public void rechargedPendings(){
        SymbolTable temp;
        SymbolTable temp2;
        Symbol temp3;
        temp3 = SymbolTable.actualSymbolTable.getSymbol("method main( )");
        if(temp3 == null)
            Error.message.add("missing void main ( ) method");
        SymbolTable tempParent = SymbolTable.actualSymbolTable;
        for(int i = 0; i < SymbolTable.pending.size(); i++){
            temp = SymbolTable.actualSymbolTable.getChild("struct "+SymbolTable.pending.get(i).getType());
            if(temp != null){
                //temp2 = SymbolTable.pendingChild.get(i);
                /*for(int j = 0; j < temp.getSymbolList().size(); j++){
                    SymbolTable.actualSymbolTable = temp2;
                    SymbolTable.actualSymbolTable.addSymbol(new Variable(temp.getSymbolList().get(j).name,temp.getSymbolList().get(j).type,""+temp.getSymbolList().get(j).size));
                    SymbolTable.actualSymbolTable = tempParent;
                }*/
                SymbolTable.pending.get(i).width = temp.getWidth();
            }else{
                Error.message.add("cannot find symbol:\n\tsymbol: "+SymbolTable.pending.get(i).getSymbolType()+" "+SymbolTable.pending.get(i).getName());
            }
        }
    }


    public void traduction(SyntaxTree tree){
        
        String subType = null;
        tree.code = new ThreeDirectionInstruction();
        switch(tree.reduction.getParentRule().getTableIndex())
        {
            /*case 0:
            //<Program> ::= class Program '{' <kleene_declaration> '}'
            break;
            case 1:
            //<kleene_declaration> ::= <declaration> <kleene_declaration>
            break;
            case 2:
            //<kleene_declaration> ::=
            break;
            case 3:
            //<declaration> ::= <structDeclaration>
            break;
            case 4:
            //<declaration> ::= <varDeclaration>
            break;
            case 5:
            //<declaration> ::= <methodDeclaration>
            break;*/
            case 6:{
            //<varDeclaration> ::= <Type> id <varDecl 1> ';'
                stringTemporal[0] = (String)tree.getReduction().getToken(1).getData();
                symbolTemporal[0] = SymbolTable.actualSymbolTable.getSymbol("variable "+ stringTemporal[0]);
                System.out.println(SymbolTable.actualSymbolTable.name+" "+stringTemporal[0]);
                System.out.println(symbolTemporal[0]);
                if(symbolTemporal[0].base.equals("Program_")){
                    symbolTemporal[0].base=symbolTemporal[0].base+symbolTemporal[0].name+"_ST";
                    tree.dataCode = symbolTemporal[0].base+" DUP("+symbolTemporal[0].totalWidth+")";
                    //Error.middleCode = tree.dataCode+Error.middleCode;
                    //Error.addMiddleCode(tree.dataCode);
                    middleDataCode.add(tree.dataCode);
                }
            }
            break;
            /*case 7:
            //<varDecl 1> ::= '[' num ']'
            break;*/
            /*case 8:
            //<varDecl 1>
            break;*/
            case 9:{
            //<structDeclaration> ::= struct id '{' <kleene_varDeclaration> '}'
                stringTemporal[0] = (String)tree.getReduction().getToken(1).getData();
                //symbolTemporal[0] = SymbolTable.actualSymbolTable.getParent().getSymbol("struct "+ stringTemporal[0]);
                SymbolTable.actualSymbolTable.moveToChildSymbolTable("struct "+stringTemporal[0]);
                //tree.dataCode = SymbolTable.actualSymbolTable.getName()+" DUP("+SymbolTable.actualSymbolTable.getWidth()+")\n";
                SymbolTable.actualSymbolTable.returnToParent();
                //Error.middleCode = tree.dataCode+Error.middleCode;
            }
            break;
            /*case 10:
            //<kleene_varDeclaration> ::= <varDeclaration> <kleene_varDeclaration>
            break;
            case 11:
            //<kleene_varDeclaration> ::=
            break;*/
            case 12:{
            //<methodDeclaration> ::= <Type> id '(' <opt_parameter> ')' <block>
                stringTemporal[0] = (String)tree.getReduction().getToken(1).getData();
                SymbolTable.actualSymbolTable.moveToChildSymbolTable("method "+stringTemporal[0]);
                tree.traduction(tree.getChildren().get(3));
                stringTemporal[1] = "( "+tree.getChildren().get(3).getType()+")";
                symbolTemporal[0] = SymbolTable.actualSymbolTable.getParent().getSymbol("method "+ stringTemporal[0]+stringTemporal[1]);
                tree.traduction(tree.getChildren().get(5));
                stringTemporal[2] = tree.getChildren().get(5).getType();

                if(symbolTemporal[0] != null){
                    booleanTemporal[0] = true;
                    do{
                        booleanTemporal[1] = false;
                        if(stringTemporal[2].contains("sub ")){
                                if(stringTemporal[2].split(" ").length > 2){
                                    stringTemporal[3] = stringTemporal[2].split(" ")[1] +" "+stringTemporal[2].replaceFirst("sub(.)*( )*sub ","");
                                    stringTemporal[2] = stringTemporal[2].split(" ")[1];
                                    booleanTemporal[1] = true;
                                    booleanTemporal[0] = false;
                                }else{
                                    stringTemporal[2] = stringTemporal[2].replaceFirst("sub ", "");
                                }
                                if(stringTemporal[2].equals("void"))
                                    booleanTemporal[0] = false;
                            }else{
                                if(stringTemporal[2].split(" ").length > 1){
                                    stringTemporal[2] = stringTemporal[2].split(" ")[1];
                                }
                            }
                        if(stringTemporal[2].equals(symbolTemporal[0].getType())){
                            subType = "void";
                        }else{
                            subType = "void";
                            //subType = "error";
                            if(booleanTemporal[0]){
                                if(stringTemporal[2].equals("void")){
                                    Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": missing return statement");
                                }else{
                                    if(symbolTemporal[0].getType().equals("void")){
                                        Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": cannot return a value from mehtod whose result type is void");
                                    }else
                                        Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": incopatible types\n\trequired: "+symbolTemporal[0].getType()+"\n\tfound: "+stringTemporal[2]);
                                }
                            }
                        }
                        if(booleanTemporal[1]){
                            stringTemporal[2] = stringTemporal[3];
                        }
                    }while(booleanTemporal[1]);
                    //tree.code = "Proc "+(String)tree.getReduction().getToken(1).getData()+"\n";
                    stringTemporal[0] = (String)tree.getReduction().getToken(1).getData();
                    tree.code.addInstruction("Proc "+stringTemporal[0] ,"methodStart");
                    //tree.code = tree.code+ tree.children.get(5).code;
                    tree.code.addInstruction(tree.children.get(5).code);
                    //tree.code = tree.code+"ProcEnd "+(String)tree.getReduction().getToken(1).getData()+"\n";
                    tree.code.addInstruction(""+SymbolTable.actualSymbolTable.getTotalWidth(),"methodSize");
                    if(!stringTemporal[0].equals("main")){
                        integerTemporal = tree.code.getLastType("methodStart", tree.code.getSize()-1);
                        tree.code.setInstruction(integerTemporal, tree.code.getInstruction(integerTemporal)+"_"+SymbolTable.actualSymbolTable.getParamNumber());
                        tree.code.addInstruction("ProcEnd "+stringTemporal[0]+"_"+SymbolTable.actualSymbolTable.getParamNumber(),"methodEnd");
                    }else
                        tree.code.addInstruction("ProcEnd "+stringTemporal[0],"methodEnd");
                    //tree.dataCode = SymbolTable.actualSymbolTable.getName()+" DUP("+SymbolTable.actualSymbolTable.getWidth()+")\n";
                    //Error.addMiddleCode("");
                    //Error.addMiddleCode(tree.code);
                    middleCode.addInstruction(" ", "blank");
                    middleCode.addInstruction(tree.code);
                    SymbolTable.actualSymbolTable.returnToParent();
                }else{
                    subType = "error";
                    Error.message.addLast("line: "+tree.getReduction().getToken(1).getLineNumber()+": cannot find symbol\n\tsymbol: method "+stringTemporal[0]+stringTemporal[1]);
                }
                
                //Error.middleCode = Error.middleCode + tree.code;
            }
            break;
            /*case 13:{
            //<opt_parameter> ::= <parameter list>
                
            }
            break;*/
            case 14:{
            //<opt_parameter> ::=
                subType = "";
            }
            break;
            /*case 15:{
            //<parameter list> ::= <parameter>
                System.out.println("parameters list!!!!!!");
            }
            break;*/
            case 16:{
            //<parameter list> ::= <parameter list> ',' <parameter>
                tree.traduction(tree.getChildren().get(0));
                tree.traduction(tree.getChildren().get(2));
                subType = tree.getChildren().get(0).getType() + tree.getChildren().get(2).getType();
            }
            break;
            /*case 17:
            //<Type> ::= int
            break;
            case 18:
            //<Type> ::= char
            break;
            case 19:
            //<Type> ::= boolean
            break;
            case 20:
            //<Type> ::= void
            break;
            case 21:
            //<Type> ::= struct id
            break;
            case 22:
            //<Type> ::= <structDeclaration>
            break;*/
            case 23:{
            //<parameter> ::= <Type> id
                symbolTemporal[0] = SymbolTable.actualSymbolTable.getSymbol("variable "+(String)tree.getReduction().getToken(1).getData());
                if(symbolTemporal[0] != null){
                    subType = symbolTemporal[0].getType()+" ";
                }else{
                    subType = "error";
                    Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": cannot find symbol\n\tsymbol: variable "+symbolTemporal[0].getName());
                }
            }
            break;
            case 24:{
            //<parameter> ::= <Type> id '[' ']'
                symbolTemporal[0] = SymbolTable.actualSymbolTable.getSymbol("variable "+(String)tree.getReduction().getToken(1).getData());
                if(symbolTemporal[0] != null){
                    subType = symbolTemporal[0].getType()+"[] ";
                }else{
                    subType = "error";
                    Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": cannot find symbol\n\tsymbol: variable "+symbolTemporal[0].getName());
                }
            }
            break;
            case 25:{
            //<block> ::= '{' <kleene_varDeclaration> <kleene_statement> '}'
                tree.traduction(tree.getChildren().get(1));
                /*if(tree.getType(tree.getChildren().get(2)).equals("void"))
                    subType = "void";
                else{
                    subType = "error";
                    
                }*/
                tree.traduction(tree.getChildren().get(2));
                stringTemporal[0] = tree.getChildren().get(2).getType();
                if(stringTemporal[0].equals("null"))
                    subType = "void";
                else
                    subType = stringTemporal[0];
                tree.code = tree.children.get(2).code;
            }
            break;
            case 26:{
            //<kleene_statement> ::= <statement> <kleene_statement>
                tree.traduction(tree.getChildren().get(0));
                stringTemporal[0] = tree.getChildren().get(0).getType();
                tree.traduction(tree.getChildren().get(1));
                stringTemporal[1] = tree.getChildren().get(1).getType();
                if(!((stringTemporal[0].equals("error"))||(stringTemporal[1].equals("error")))){
                    if((stringTemporal[0].equals("void"))&&((stringTemporal[1].equals("void"))))
                        subType = "void";
                    else{
                        //System.out.println("statement "+stringTemporal[0]+" "+stringTemporal[1]+"-----------------------------------");
                        if(!(stringTemporal[0].equals("void"))){
                            if(!stringTemporal[0].startsWith("sub ")){
                                subType = stringTemporal[0];
                                if(!stringTemporal[1].equals("null")){
                                    Error.message.add("line: "+(tree.getChildren().get(0).getReduction().getToken(1).getLineNumber()+1)+": unreachable statement");
                                }
                            }else{
                                //stringTemporal[0] = stringTemporal[0].replaceFirst("sub ", "");
                                if(stringTemporal[1].startsWith("sub "))
                                    subType = stringTemporal[0]+" "+stringTemporal[1];
                                else
                                    subType = stringTemporal[0];
                            }
                        }
                        else{
                            if(!stringTemporal[1].equals("null"))
                                subType = stringTemporal[1];
                            else{
                                if(stringTemporal[1].startsWith("sub ")){
                                    subType = stringTemporal[1];
                                }else
                                    subType = "void";
                            }
                        }
                    }
                }else{
                    subType = "error";
                }
                //tree.code = tree.children.get(0).code+tree.children.get(1).code;
                tree.code = tree.children.get(0).code;
                tree.code.addInstruction(tree.children.get(1).code);
            }
            break;
            case 27:{
            //<kleene_statement> ::=
                subType = "null";
                tree.code = null;
            }
            break;
            case 28:{
            //<statement> ::= <block>
                tree.code = tree.children.get(0).code;
            }
            break;
            /*case 29:
            //<statement> ::= <selection>
            break;
            /*case 30:
            //<statement> ::= <iteration>
            break;*/
            case 31:{
            //<statement> ::= <return> ';'
                tree.traduction(tree.getChildren().get(0));
                subType = tree.getChildren().get(0).getType();
                //tree.code = "return "+tree.children.get(0).code+"\n";
                tree.code = tree.children.get(0).code;
            }
            break;
            case 32:{
            //<statement> ::= <assign> ';'
                tree.traduction(tree.getChildren().get(0));
                subType = tree.getChildren().get(0).getType();
                tree.code = tree.children.get(0).code;
            }
            break;
            /*case 33:
            //<statement> ::= <opt_expression> ';'
            break;*/
            case 34:{
            //<selection> ::= if '(' <expression> ')' <block> <opt_else_block>
                tree.traduction(tree.getChildren().get(4));
                tree.traduction(tree.getChildren().get(2));
                stringTemporal[0] = tree.getChildren().get(2).getType();
                if(stringTemporal[0].split(" ").length > 1){
                    stringTemporal[0] = stringTemporal[0].split(" ")[1];
                }
                if(stringTemporal[0].equals("boolean")){
                    /*if((tree.getType(tree.getChildren().get(4)).equals("void"))&&(tree.getType(tree.getChildren().get(5)).equals("void"))){
                        subType = "void";
                    }
                    else{
                        subType = "error";
                    }*/
                    //subType = "void";
                }else{
                    //subType = "void";
                    Error.message.add("line: "+tree.getReduction().getToken(0).getLineNumber()+": incopatible types\n\trequired: boolean"+"\n\tfound: "+stringTemporal[0]);
                }
                tree.traduction(tree.getChildren().get(4));
                stringTemporal[0] = tree.getChildren().get(4).getType();
                tree.traduction(tree.getChildren().get(5));
                stringTemporal[1] = tree.getChildren().get(5).getType();
                if(stringTemporal[0].equals("void")){
                    if(stringTemporal[1].equals("void")){
                        subType = "sub void";
                    }else{
                        subType = "sub "+stringTemporal[1];
                    }
                }else{
                    if(stringTemporal[1].equals("void")){
                        subType = "sub "+ stringTemporal[0];
                    }else{
                        if(!stringTemporal[0].equals(stringTemporal[1])){
                            subType = "sub error";
                            Error.message.add("line: "+tree.getReduction().getToken(0).getLineNumber()+": incompatible return types");
                        }else{
                            subType = "sub "+ stringTemporal[0];
                        }
                    }
                }
                tree.labelTrue = new Label();
                tree.labelFalse = new Label();
                tree.labelNext = new Label();
                tree.code = tree.children.get(2).gda.getCode();
                //tree.code = tree.code+"if "+tree.children.get(2).gda.getVal()+" == 1 goto "+tree.labelTrue+"\n";
                tree.code.addInstruction("if "+tree.children.get(2).gda.getVal()+" == 1 goto "+tree.labelTrue, "ifStart");
                //tree.code = tree.code+tree.children.get(5).code;
                tree.code.addInstruction(tree.children.get(5).code);
                //tree.code = tree.code+"goto "+tree.labelNext.getName()+"\n";
                tree.code.addInstruction("goto "+tree.labelNext.getName(),"gotoInconditional");
                //tree.code = tree.code+tree.labelTrue+":\n"+tree.children.get(4).code+tree.labelNext+":\n";
                //tree.code.addInstruction(tree.labelTrue+":\n"+tree.children.get(4).code+tree.labelNext+":","ifRest");
                tree.code.addInstruction(tree.labelTrue+":","label");
                tree.code.addInstruction(tree.children.get(4).code);
                tree.code.addInstruction(tree.labelNext+":","label");
                tree.children.get(2).gda.recicleTemporal();
            }
            break;
            case 35:{
            //<opt_else_block> ::= else <block>
                /*if(tree.getType(tree.getChildren().get(1)).equals("void")){
                    subType = "void";
                }else{
                    subType = "error";
                }*/
                tree.traduction(tree.getChildren().get(1));
                subType = tree.getChildren().get(1).getType();
                tree.code = tree.children.get(1).code;
            }
            break;
            case 36:{
            //<opt_else_block>
                subType = "void";
                tree.code = null;
            }
            break;
            case 37:{
            //<iteration> ::= while '(' <expression> ')' <block>
                tree.traduction(tree.getChildren().get(2));
                stringTemporal[0] = tree.getChildren().get(2).getType();
                if(stringTemporal[0].equals("boolean")){
                    /*if(tree.getType(tree.getChildren().get(4)).equals("void")){
                        subType = "void";
                    }else{
                        subType = "error";
                    }*/
                    //subType = "void";
                }else{
                    //subType = "void";
                    Error.message.add("line: "+tree.getReduction().getToken(0).getLineNumber()+": incopatible types\n\trequired: boolean"+"\n\tfound: "+stringTemporal[0]);
                }

                tree.traduction(tree.getChildren().get(4));
                subType = "sub "+ tree.getChildren().get(4).getType();
                tree.code = tree.children.get(2).gda.getCode();
                tree.labelNext = tree.children.get(2).gda.getNextLabel();
                tree.labelFalse = new Label();
                //tree.code = tree.code+"ifFalse "+tree.children.get(2).gda.getVal()+" == 1 goto "+tree.labelFalse+"\n";
                tree.code.addInstruction("ifFalse "+tree.children.get(2).gda.getVal()+" == 1 goto "+tree.labelFalse,"whileStart");
                //tree.code = tree.code+tree.children.get(4).code;
                tree.code.addInstruction(tree.children.get(4).code);
                //tree.code = tree.code+"goto "+tree.labelNext+"\n"+tree.labelFalse+"\n";
                //tree.code.addInstruction("goto "+tree.labelNext+"\n"+tree.labelFalse+":","whileRest");
                tree.code.addInstruction("goto "+tree.labelNext,"gotoInconditional");
                tree.code.addInstruction(tree.labelFalse+":","label");
                tree.children.get(2).gda.recicleTemporal();
            }
            break;
            case 38:{
            //<return> ::= return <opt_expression>
                tree.traduction(tree.getChildren().get(1));
                subType = tree.getChildren().get(1).getType();
                //tree.code = tree.children.get(1).gda.getCode()+tree.children.get(1).gda.getVal();
                tree.code.addInstruction(tree.children.get(1).gda.getCode());
                tree.code.addInstruction("return "+tree.children.get(1).gda.getVal(),"return");
                tree.children.get(1).gda.recicleTemporal();
            }
            break;
            case 39:{
            //<assign> ::= <location> '=' <expression>
               
                //----------------------------------------------------------------------------------------------------------------
                /*stringTemporal[1] = tree.getType(tree.getChildren().get(0));
                symbolTableTemporal = SymbolTable.actualSymbolTable;
                booleanTemporal[1] = false;
                booleanTemporal[0] = false;
                while(stringTemporal[1].startsWith("struct ")){
                    booleanTemporal[1] = true;
                    //ttype = "variable";
                    stringTemporal[0] = stringTemporal[1].split(" ")[1];
                    symbolTableTemporal = symbolTableTemporal.getChildRecursive("variable "+stringTemporal[0]);
                    if(symbolTableTemporal != null){
                        symbolTemporal[0] = symbolTableTemporal.getSymbol("variable "+stringTemporal[0]);
                        stringTemporal[1] = stringTemporal[1].replaceFirst("struct "+stringTemporal[0]+" ", "");
                        if(stringTemporal[1].startsWith("[] ")){
                            stringTemporal[1] = stringTemporal[1].replaceFirst("\\[\\] ", "");
                            if(symbolTemporal[0].getSize() == 1){
                                Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": incompatible types\n\trequired: "+symbolTemporal[0].getType()+"\n\tfound: "+symbolTemporal[0].getType()+"[]");
                            }
                        }else{
                            if(symbolTemporal[0].getSize() > 1){
                                Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": incompatible types\n\trequired: "+symbolTemporal[0].getType()+"[]\n\tfound: "+symbolTemporal[0].getType());
                            }
                        }
                    }else{
                        booleanTemporal[0] = true;
                        subType = "void";
                        Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": cannot find symbol\n\tsymbol: "+stringTemporal[0]);
                        break;
                    }
                }
                if(!booleanTemporal[0]){
                    if(!booleanTemporal[1]){
                        symbolTemporal[0] = SymbolTable.actualSymbolTable.getSymbol(stringTemporal[1]);
                    }else{
                        symbolTemporal[0] = symbolTableTemporal.getSymbol(stringTemporal[1]);
                    }
                    stringTemporal[0] = tree.getType(tree.getChildren().get(2));
                    if(symbolTemporal[0] != null){
                        if((symbolTemporal[0].getSize() == 1)||((symbolTemporal[0].getSize() > 1)&&(stringTemporal[1].contains("[]")))){
                            if(symbolTemporal[0].getType().equals(stringTemporal[0])){
                                subType = "void";
                            }else{
                                subType = "void";
                                Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": incompatible types\n\trequired: "+symbolTemporal[0].type+"\n\tfound: " +stringTemporal[0]);
                            }
                        }else{
                            subType = "void";
                            Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": incompatible types\n\trequired: "+symbolTemporal[0].getType()+"[]\n\tfound: "+stringTemporal[0]);
                        }
                    }else{
                        subType = "void";
                        Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": cannot find symbol\n\tsymbol: "+stringTemporal[1]);
                    }
                }*/
                //-----------------------------------------------------------------------------------------------------------------------------------------
                tree.traduction(tree.getChildren().get(0));
                stringTemporal[0] = tree.getChildren().get(0).getType();
                if(!stringTemporal[0].equals("error")){
                    tree.traduction(tree.getChildren().get(2));
                    stringTemporal2[1] = tree.getChildren().get(2).getType();
                    stringTemporal = stringTemporal[0].split(" ");
                    if(stringTemporal2[1].split(" ").length > 1){
                        stringTemporal2 = stringTemporal2[1].split(" ");
                        if(!stringTemporal2[3].equals("null")){
                            if(Integer.parseInt(stringTemporal2[2]) == 1){
                                Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": array index found but not requiered\n\tsymbol: "+stringTemporal2[0]);
                            }
                        }else{
                            if(Integer.parseInt(stringTemporal2[2]) > 1){
                                Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": array index requiered but not found\n\tsymbol: "+stringTemporal2[0]);
                            }
                        }
                    }
                    if(!stringTemporal[3].equals("null")){
                        if(Integer.parseInt(stringTemporal[2]) == 1){
                            Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": array index found but not requiered\n\tsymbol: "+stringTemporal[0]);
                        }else{
                            if(!(stringTemporal[1].equals(stringTemporal2[1]))){
                                Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": incompatible types\n\trequired: "+stringTemporal[1]+"\n\tfound: " +stringTemporal2[1]);
                            }
                        }
                    }else{
                        if(Integer.parseInt(stringTemporal[2]) > 1){
                            if(stringTemporal2[0].split(" ").length > 1){
                                Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": array index requiered but not found\n\tsymbol: "+stringTemporal[0]);
                            }else{
                                Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": array index requiered but not found\n\tsymbol: "+stringTemporal[0]);
                            }
                        }else{
                            if(!(stringTemporal[1].equals(stringTemporal2[1]))){
                                Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": incompatible types\n\trequired: "+stringTemporal[1]+"\n\tfound: " +stringTemporal2[1]);
                            }
                        }
                    }
                }
                subType = "void";
                if(Error.message.size() == 0){
                    //tree.code = tree.getChildren().get(2).gda.getCode()+tree.getChildren().get(0).gda.getCode()+tree.getChildren().get(0).gda.getVal()+" = "+tree.getChildren().get(2).gda.getVal()+"\n";
                    tree.code.addInstruction(tree.getChildren().get(2).gda.getCode());
                    tree.code.addInstruction(tree.getChildren().get(0).gda.getCode());
                    tree.code.addInstruction(tree.getChildren().get(0).gda.getVal()+" = "+tree.getChildren().get(2).gda.getVal(),"assign");
                    tree.getChildren().get(0).gda.recicleTemporal();
                    tree.getChildren().get(2).gda.recicleTemporal();
                }
            }
            break;
            /*case 40:
            //<opt_expression> ::= <expression>
            break;
            case 41:
            //<opt_expression> ::=
            break;*/
            case 42:{
            //<expression> ::= <Rel Exp> <conditionalop> <expression>
                tree.traduction(tree.getChildren().get(1));
                tree.traduction(tree.getChildren().get(0));
                if(tree.getChildren().get(0).getType().split(" ").length > 1)
                    stringTemporal = tree.getChildren().get(0).getType().split(" ");
                else
                    stringTemporal[1] = tree.getChildren().get(0).getType();
                tree.traduction(tree.getChildren().get(2));
                if(tree.getChildren().get(2).getType().split(" ").length > 1)
                    stringTemporal2 = tree.getChildren().get(2).getType().split(" ");
                else
                    stringTemporal2[1] = tree.getChildren().get(2).getType();
                if(stringTemporal[1].equals("boolean")){
                    if(stringTemporal2[1].equals("boolean")){
                        subType = "boolean";
                        System.out.println(tree.children.get(1).getReduction().getToken(0).getLineNumber());
                        tree.gda = new GDA(tree.getChildren().get(1).data, tree.getChildren().get(0).gda, tree.getChildren().get(2).gda);
                    }else{
                        subType = "error";
                        Error.message.add("line: "+tree.getChildren().get(1).getReduction().getToken(0).getLineNumber()+": incopatible types\n\trequired: boolean\n\tfound: "+stringTemporal2[1]);
                    }
                }else{
                    subType = "error";
                    Error.message.add("line: "+tree.getChildren().get(1).getReduction().getToken(0).getLineNumber()+": incopatible types\n\trequired: boolean\n\tfound: "+stringTemporal[1]);
                }
            }
            break;
            /*case 43:
            //<expression> ::= <Rel Exp>
            break;*/
            case 44:{
            //<Rel Exp> ::= <Add Exp> <relop> <Rel Exp>
                tree.traduction(tree.getChildren().get(1));
                tree.traduction(tree.getChildren().get(0));
                if(tree.getChildren().get(0).getType().split(" ").length > 1)
                    stringTemporal = tree.getChildren().get(0).getType().split(" ");
                else
                    stringTemporal[1] = tree.getChildren().get(0).getType();
                tree.traduction(tree.getChildren().get(2));
                if(tree.getChildren().get(2).getType().split(" ").length > 1)
                    stringTemporal2 = tree.getChildren().get(2).getType().split(" ");
                else
                    stringTemporal2[1] = tree.getChildren().get(2).getType();
                if((stringTemporal[1].equals("int")&&(stringTemporal2[1].equals("int")))||(stringTemporal[1].equals("char")&&(stringTemporal2[1].equals("char")))||(stringTemporal[1].equals("boolean")&&(stringTemporal2[1].equals("boolean")))){
                    subType = "boolean";
                    //Construcción de GDA-------------------------------
                    tree.gda = new GDA(tree.getChildren().get(1).data, tree.getChildren().get(0).gda, tree.getChildren().get(2).gda);
                }else{
                    subType = "error";
                    Error.message.add("line: "+tree.getChildren().get(1).getReduction().getToken(0).getLineNumber()+": incopatible types\n\trequired: boolean & boolean | int & int | char & char\n\tfound: "+stringTemporal[1] +" & "+stringTemporal2[1]);
                }
            }
            break;
            /*case 45:
            //<Rel Exp> ::= <Add Exp>
            break;*/
            case 46:{
            //<Add Exp> ::= <Mult Exp> <addop> <Add Exp>
                tree.traduction(tree.getChildren().get(1));
                tree.traduction(tree.getChildren().get(0));
                if(tree.getChildren().get(0).getType().split(" ").length > 1)
                    stringTemporal = tree.getChildren().get(0).getType().split(" ");
                else
                    stringTemporal[1] = tree.getChildren().get(0).getType();
                tree.traduction(tree.getChildren().get(2));
                if(tree.getChildren().get(2).getType().split(" ").length > 1)
                    stringTemporal2 = tree.getChildren().get(2).getType().split(" ");
                else
                    stringTemporal2[1] = tree.getChildren().get(2).getType();
                if(stringTemporal[1].equals("int")){
                    if(stringTemporal2[1].equals("int")){
                        subType = "int";
                        //Construcción de GDA-------------------------------
                        tree.gda = new GDA(tree.getChildren().get(1).data, tree.getChildren().get(0).gda, tree.getChildren().get(2).gda);
                        System.out.println(tree.gda);
                    }else{
                        subType = "error";
                        Error.message.add("line: "+tree.getChildren().get(1).getReduction().getToken(0).getLineNumber()+": operator can be applied to "+stringTemporal2[1]);
                    }
                }else{
                    subType = "error";
                    Error.message.add("line: "+tree.getChildren().get(1).getReduction().getToken(0).getLineNumber()+": operator can't be applied to "+stringTemporal[1]);
                }
            }
            break;
            /*case 47:
            //<Add Exp> ::= <Mult Exp>
            break;*/
            case 48:{
            //<Mult Exp> ::= <Negate Exp> <mulop> <Mult Exp>
                tree.traduction(tree.getChildren().get(1));
                tree.traduction(tree.getChildren().get(0));
                if(tree.getChildren().get(0).getType().split(" ").length > 1)
                    stringTemporal = tree.getChildren().get(0).getType().split(" ");
                else
                    stringTemporal[1] = tree.getChildren().get(0).getType();
                tree.traduction(tree.getChildren().get(2));
                if(tree.getChildren().get(2).getType().split(" ").length > 1)
                    stringTemporal2 = tree.getChildren().get(2).getType().split(" ");
                else
                    stringTemporal2[1] = tree.getChildren().get(2).getType();
                if(stringTemporal[1].equals("int")){
                    if(stringTemporal2[1].equals("int")){
                        subType = "int";
                        //Construcción de GDA-------------------------------
                        tree.gda = new GDA(tree.getChildren().get(1).data, tree.getChildren().get(0).gda, tree.getChildren().get(2).gda);
                        System.out.println(tree.gda);
                    }else{
                        subType = "error";
                        Error.message.add("line: "+tree.getChildren().get(1).getReduction().getToken(0).getLineNumber()+": operator can be applied to : "+stringTemporal2[1]);
                    }
                }else{
                    subType = "error";
                    Error.message.add("line: "+tree.getChildren().get(1).getReduction().getToken(0).getLineNumber()+": operator can't be applied to "+stringTemporal[1]);
                }
            }
            break;
            /*case 49:
            //<Mult Exp> ::= <Negate Exp>
            break;*/
            case 50:{
            //<Negate Exp> ::= '-' <Value>
                tree.traduction(tree.getChildren().get(1));
                if(tree.getChildren().get(1).getType().split(" ").length > 1)
                    stringTemporal = tree.getChildren().get(1).getType().split(" ");
                else
                    stringTemporal[1] = tree.getChildren().get(1).getType();
                if(stringTemporal[1].equals("int")){
                    subType = "int";
                    //this.gda = new GDA
                    tree.gda = new GDA("~", tree.children.get(1).gda);
                }else{
                    subType = "error";
                    Error.message.add("line: "+tree.getReduction().getToken(0).getLineNumber()+": operator can't be applied to "+stringTemporal[1]);
                }
            }
            break;
            case 51:{
            //<Negate Exp> ::= '!' <Value>
                tree.traduction(tree.getChildren().get(1));
                if(tree.getChildren().get(1).getType().split(" ").length > 1)
                    stringTemporal = tree.getChildren().get(1).getType().split(" ");
                else
                    stringTemporal[1] = tree.getChildren().get(1).getType();
                if(stringTemporal[1].equals("boolean")){
                    subType = "boolean";
                }else{
                    subType = "error";
                    Error.message.add("line: "+tree.getReduction().getToken(0).getLineNumber()+": operator can't be applied to "+stringTemporal[1]);
                }
            }
            break;
            /*case 52:
            //<Negate Exp> ::= <Value>
            break;*/
            case 53:
            //<conditionalop> ::= '&&'
                tree.data = "&&";
            break;
            case 54:
            //<conditionalop> ::= '||'
                tree.data = "||";
            break;
            case 55:
            //<relop> ::= '<='
                tree.data = "<=";
            break;
            case 56:
            //<relop> ::= '<'
                tree.data = "<";
            break;
            case 57:
            //<relop> ::= '>'
                tree.data = ">";
            break;
            case 58:
            //<relop> ::= '>='
                tree.data = ">=";
            break;
            case 59:
            //<relop> ::= '=='
                tree.data = "==";
            break;
            case 60:
            //<relop> ::= '!='
                tree.data = "!=";
            break;
            case 61:
            //<addop> ::= '+'
                tree.data = "+";
            break;
            case 62:
            //<addop> ::= '-'
                tree.data = "-";
            break;
            case 63:
            //<mulop> ::= '*'
                tree.data = "*";
            break;
            case 64:
            //<mulop> ::= '/'
                tree.data = "/";
            break;
            case 65:
            //<mulop> ::= '%'
                tree.data = "%";
            break;
            /*case 66:
            //<Value> ::= <literal>
            break;*/
            case 67:{
            //<Value> ::= '(' <expression> ')'
                tree.traduction(tree.getChildren().get(1));
                subType = tree.getChildren().get(1).getType();
                tree.gda = tree.getChildren().get(1).gda;
            }
            break;
            /*case 68:
            //<Value> ::= <methodCall>
            break;
            case 69:
            //<Value> ::= <location>
            break;*/
            case 70:{
            //<location> ::= <simpleLocation> '.' <location>
                //--------------------------------------------------------------------------------------
                /*
                stringTemporal[0]= tree.getType(tree.getChildren().get(0)).replace("variable", "struct");
                stringTemporal[1] = tree.getType(tree.getChildren().get(2));
                subType = stringTemporal[0]+" "+stringTemporal[1];
                */
                //--------------------------------------------------------------------------------------
                tree.traduction(tree.getChildren().get(0));
                stringTemporal = tree.getChildren().get(0).getType().split(" ");
                SymbolTable symbolTableTemp = SymbolTable.actualSymbolTable;
                SymbolTable.actualSymbolTable = SymbolTable.actualSymbolTable.getChildRecursive("struct "+stringTemporal[1]);
                if(SymbolTable.actualSymbolTable != null){
                    symbolTemporal[0] = symbolTableTemp.getSymbol("variable "+stringTemporal[0]);
                    if(!stringTemporal[3].equals("null")){
                        if(symbolTemporal[0].getSize() == 1){
                            subType = "error";
                            Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": array index found but not requered\n\tsymbol: "+stringTemporal[0]);
                        }else{
                            tree.traduction(tree.getChildren().get(2));
                            subType = tree.getChildren().get(2).getType();
                            tree.gda = new GDA(symbolTemporal[0], tree.children.get(2).gda);
                        }
                    }else{
                        if(symbolTemporal[0].getSize() > 1){
                            subType = "error";
                            Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": array index requiered but not found\n\tsymbol: "+stringTemporal[0]);
                        }else{
                            tree.traduction(tree.getChildren().get(2));
                            subType = tree.getChildren().get(2).getType();
                            tree.gda = new GDA(symbolTemporal[0], tree.children.get(2).gda);
                        }
                    }
                }else{
                    SymbolTable.actualSymbolTable = symbolTableTemp;
                    subType = "error";
                    Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": cannot find symbol\n\tsymbol: "+stringTemporal[0]);
                }
                SymbolTable.actualSymbolTable = symbolTableTemp;
            }
            break;
            /*case 71:
            //<location> ::= <simpleLocation>
            break;*/
            case 72:{
            //<simpleLocation> ::= id '[' <expression> ']'
                //--------------------------------------------------------------------------------
                /*
                stringTemporal[0] = tree.getType(tree.getChildren().get(2));
                if(stringTemporal[0].equals("int")){
                    subType = "variable "+(String) tree.getReduction().getToken(0).getData()+" []";
                }else{
                    subType = "error";
                    Error.message.add("line: "+tree.getReduction().getToken(0).getLineNumber()+": incompatible types\n\trequired: int\n\tfound: "+stringTemporal[0]);
                }
                */
                //--------------------------------------------------------------------------------
                tree.traduction(tree.getChildren().get(2));
                stringTemporal[0] = tree.getChildren().get(2).getType();
                if(stringTemporal[0].equals("int")){
                    stringTemporal[0] = "variable "+(String) tree.getReduction().getToken(0).getData();
                    symbolTemporal[1] = SymbolTable.actualSymbolTable.getSymbol(stringTemporal[0]);
                    if(symbolTemporal[1] != null){
                        subType = symbolTemporal[1].getName()+" "+symbolTemporal[1].getType()+" "+symbolTemporal[1].getSize()+" []";
                        tree.gda = new GDA(symbolTemporal[1],tree.children.get(2).gda);
                    }else{
                        subType = "error";
                        Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": cannot find symbol\n\tsymbol: "+stringTemporal[1]);
                    }
                }else{
                    subType = "error";
                    Error.message.add("line: "+tree.getReduction().getToken(0).getLineNumber()+": incompatible types\n\trequired: int\n\tfound: "+stringTemporal[0]);
                }
            }
            break;
            case 73:{
            //<simpleLocation> ::= id
                //-------------------------------------------------------------------------
                /*
                subType = "variable " + (String) tree.getReduction().getToken(0).getData();
                */
                //-------------------------------------------------------------------------
                stringTemporal[0] = "variable " + (String) tree.getReduction().getToken(0).getData();
                symbolTemporal[1] = SymbolTable.actualSymbolTable.getSymbol(stringTemporal[0]);
                if(symbolTemporal[1] != null){
                    subType = symbolTemporal[1].getName()+" "+symbolTemporal[1].getType()+" "+symbolTemporal[1].getSize()+" null";
                    //Aqui se crea el GDA-------------------------------------------------------------------------
                    tree.gda = new GDA(symbolTemporal[1]);
                }else{
                    subType = "error";
                    Error.message.add("line: "+tree.getReduction().getToken(0).getLineNumber()+": cannot find symbol\n\tsymbol: "+stringTemporal[0]);
                }
            }
            break;
            case 74:{
            //<methodCall> ::= id '(' <opt_arg_separated> ')'
                tree.gdaParameters = new LinkedList();
                tree.gdaParametersbool = false;
                tree.traduction(tree.getChildren().get(2));
                if(!tree.gdaParametersbool){
                    tree.gdaParameters.add(tree.children.get(2).gda);
                }
                stringTemporal[0] = tree.getChildren().get(2).getType();
                if(!tree.gdaParametersbool){
                    if (stringTemporal[0].split(" ").length > 1){
                        stringTemporal[0] = stringTemporal[0].split(" ")[1];
                    }
                }
                if(stringTemporal[0].length() == 0)
                    stringTemporal[1] = "( "+stringTemporal[0]+")";
                else
                    stringTemporal[1] = "( "+stringTemporal[0]+" )";
                symbolTemporal[0] = SymbolTable.actualSymbolTable.getParent().getSymbol("method "+((String)tree.getReduction().getToken(0).getData())+stringTemporal[1]);
                if(symbolTemporal[0] != null){
                    subType = symbolTemporal[0].getType();
                    tree.gda = new GDA(symbolTemporal[0],tree.gdaParameters);
                }else{
                    subType = "error";
                    Error.message.add("line: "+tree.getReduction().getToken(0).getLineNumber()+": cannot find symbol\n\tsymbol: method"+((String)tree.getReduction().getToken(0).getData())+stringTemporal[1]);
                }
                //subType = "method: " + (String) tree.getReduction().getToken(0).getData();
            }
            break;
            /*case 75:
            //<opt_arg_separated> ::= <arg list>
            break;*/
            case 76:{
            //<opt_arg_separated> ::=
                subType = "";
            }
            break;
            /*case 77:
            //<arg list> ::= <arg>
            break;*/
            case 78:{
            //<arg list> ::= <arg list> ',' <arg>
                tree.traduction(tree.getChildren().get(0));
                tree.gdaParametersbool = true;
                stringTemporal[0] = tree.getChildren().get(0).getType();
                if(stringTemporal[0].split(" ").length > 1){
                    stringTemporal = stringTemporal[0].split(" ");
                    if(!stringTemporal[3].equals("null")){
                        if(Integer.parseInt(stringTemporal[2]) == 1){
                            Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": array index found but not requered\n\tsymbol: "+stringTemporal[0]);
                            subType = "error";
                        }else{

                            tree.gdaParameters.add(tree.children.get(0).gda);
                            subType = stringTemporal[1];
                        }
                    }else{
                        tree.gdaParameters.add(tree.children.get(0).gda);
                        if(Integer.parseInt(stringTemporal[2]) > 1){
                            subType = stringTemporal[1]+"[]";
                        }else{
                            subType = stringTemporal[1];
                        }
                    }
                }else{
                    tree.gdaParameters.add(tree.children.get(0).gda);
                    subType = stringTemporal[0];
                }
                tree.traduction(tree.getChildren().get(2));
                
                stringTemporal[0] = tree.getChildren().get(2).getType();
                if(stringTemporal[0].split(" ").length > 1){
                    stringTemporal = stringTemporal[0].split(" ");
                    if(!stringTemporal[3].equals("null")){
                        if(Integer.parseInt(stringTemporal[2]) == 1){
                            Error.message.add("line: "+tree.getReduction().getToken(1).getLineNumber()+": array index found but not requered\n\tsymbol: "+stringTemporal[0]);
                            subType = "error";
                        }else{
                            subType = subType + " " + stringTemporal[1];
                            tree.gdaParameters.add(tree.children.get(2).gda);
                        }
                    }else{
                        tree.gdaParameters.add(tree.children.get(2).gda);
                        if(Integer.parseInt(stringTemporal[2]) > 1){
                            subType = subType + " " + stringTemporal[1]+"[]";
                        }else{
                            subType = subType + " " + stringTemporal[1];
                        }
                    }
                }else{
                    tree.gdaParameters.add(tree.children.get(2).gda);
                    subType = subType + " " + stringTemporal[0];
                }
            }
            break;
            /*case 79:{
            //<arg> ::= <expression>
                System.out.println("entro aka a un parametro!!!!!!!!!!!!!!!!!!!!!");
            }
            break;*/
            /*case 80:
            //<literal> ::= <int_literal>
            break;
            case 81:
            //<literal> ::= <char_literal>
            break;
            case 82:
            //<literal> ::= <bool_literal>
            break;*/
            case 83:{
            //<int_literal> ::= num
                subType = "int";
                tree.data = (String)tree.reduction.getToken(0).getData();
                tree.gda = new GDA(tree.data);
                tree.width = 4;
            }
            break;
            case 84:{
            //<char_literal> ::= character
                subType = "char";
                tree.data = (String)tree.reduction.getToken(0).getData();
                tree.gda = new GDA(tree.data);
                tree.width = 2;
            }
            break;
            case 85:{
            //<bool_literal> ::= true
                subType = "boolean";
                tree.data = "1";
                tree.gda = new GDA(tree.data);
            }
            break;
            case 86:{
            //<bool_literal> ::= false
                subType = "boolean";
                tree.data = "0";
                tree.gda = new GDA(tree.data);
                tree.width = 1;
            }
            break;
            default:{
                subType = null;
                for(int i = 0; i < tree.getChildren().size(); i++)
                    if(tree.getChildren().get(i).hasReduction()){
                        tree.traduction(tree.getChildren().get(i));
                        subType = tree.getChildren().get(i).getType();
                    }
            }break;
        }
        tree.type = subType;
    }

    public String getType(){
        return this.type;
    }

    public String getElement(){
        return this.element;
    }

    public String getLexema(SyntaxTree tree){
        
        return null;
    }

    public Reduction getReduction(){
        return this.reduction;
    }

    public LinkedList<SyntaxTree> getChildren(){
        return this.children;
    }

    public boolean hasReduction(){
        return this.hasReduction;
    }

    public String toString(){
        String s = this.element+": ";
        if (this.children.size() == 0)
            return this.element;
        else{
        for(int i = 0; i < this.children.size(); i++){
            s = s +" - "+ children.get(i).toString();
        }
        return s;
        }
    }
}